package com.apes.fn.scm.retailOrder.service.account.retailReturn;

import com.apes.fn.scm.retailOrder.model.RetailOrderItem;
import com.apes.fn.scm.retailOrder.service.account.RetailReturnVoucher;
import com.apes.fn.scm.retailReturn.RetailReturn;
import com.apes.fn.server.servicePlan.model.ClientInvoiceRules;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.fn.server.servicePlan.model.ServicePlanItem;
import com.apes.fn.server.servicePlan.repository.ServicePlanRepository;
import com.apes.fn.server.servicePlan.service.ClientInvoiceRulesService;
import com.apes.framework.api.SpringManager;
import com.apes.scm.account.account.model.AccountingMethod;
import com.apes.scm.account.account.model.InventoryMode;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherRepository;
import com.apes.scm.voucher.service.BusinessType;
import com.apes.scm.voucher.service.VoucherType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 单位客户销售退回
 * @author wuq
 * @Time 2023-3-31 10:15
 * @Description
 */
@RetailReturnAccount(value = "returnUnitClient", name = "零售有单异业退货生成销售退回凭证")
@Service
public class RetailReturnUnitClientVoucherService implements RetailReturnVoucher {

    @Autowired
    private VoucherRepository voucherRepository;
    @Autowired
    private ClientInvoiceRulesService clientInvoiceRulesService;

    @Override
    public Voucher process(RetailReturn retailReturn) {
        
        // 区分是否为跨公司销售，这里只退门店的销售凭证
        ServicePlan servicePlan = SpringManager.getBean(ServicePlanRepository.class).findOne( retailReturn.getSaleOrder().getSource());
        List<ServicePlanItem> unitClientPlanItems = servicePlan.getServicePlanItems().stream()
                .filter(servicePlanItem -> Objects.nonNull(servicePlanItem.getUnitClient()))
                .collect(Collectors.toList());

        // 查询单位客户挂账规则
        PartyRole unitClient = unitClientPlanItems.get(0).getUnitClient();
        ClientInvoiceRules clientInvoiceRule = clientInvoiceRulesService.findClientInvoiceRules(retailReturn.getDept(), unitClient);
        if (Objects.isNull(clientInvoiceRule))
            throw new RuntimeException("没有找到 (" + unitClient.getId() + ") " + unitClient.getName() + "的开票规则，请检查！");

        // 判断是否为开票公司
        if (clientInvoiceRule.getCompany().getId().equals(retailReturn.getCompany().getId())) {
            // 为开票公司
           return returnProcess(retailReturn, clientInvoiceRule.getCustomer());
        } else {
            // 非开票公司
           return returnProcess(retailReturn, clientInvoiceRule.getCompany());
        }
    }


    private Voucher returnProcess(RetailReturn retailReturn, PartyRole customer){
        Voucher voucher = new Voucher();
        voucher.setReturned(true);
        voucher.setBusinessType(BusinessType.SALE_RETURN);
        voucher.setInventoryMode(InventoryMode.IM_OWN);     //设置库存模式：自有经销
        voucher.setAccountingMethod(AccountingMethod.AM_PURCHASE);  // 核算方式：采购

        // 主表信息
        voucher.setCompany(retailReturn.getDept().getCompany());
        voucher.setDept(retailReturn.getDept());
        voucher.setClerk(retailReturn.getClerk()); //业务员
        voucher.setPartner(customer.getParty().getPartyRoleByType("Customer"));

        voucher.setScene(retailReturn.getScene());
        voucher.setOrigin(retailReturn.getId());
        voucher.setOriginBusinessType(retailReturn.getInnerBusinessType());
        voucher.setSource(retailReturn.getId());
        voucher.setSourceBusinessType(retailReturn.getInnerBusinessType());
        voucher.setClassification(VoucherType.UNIT_CLIENT_RETURN);

        Voucher source = findVoucher(retailReturn, voucher.getPartner());
        voucher.setVoucher(source);
        voucher.setPartner(source.getPartner());    // 赋值原销售客户

        // 明细数据
        voucher.setVoucherItems(getItems(retailReturn, voucher));
        return voucher;
    }

    private Voucher findVoucher(RetailReturn retailReturn, PartyRole customer) {
        RetailOrderItem retailOrderItem = retailReturn.getSaleItems().iterator().next().getRetailOrderItem();   // 获取明细行号
        Voucher originSaleVoucher = voucherRepository.findSaleVoucherByCompanyAndItemOrigin(retailReturn.getCompany(), customer, retailOrderItem.getId());
        Optional.ofNullable(originSaleVoucher).orElseThrow( () -> new RuntimeException("单位客户退回时，没有找到原销售凭证！"));
        return originSaleVoucher;
    }

    /**
     * 获取异业合作明细
     *
     * @param saleReturn 退回明细
     * @param voucher    销售凭证
     * @return Set<VoucherItem>
     */
    private Set<VoucherItem> getItems(RetailReturn saleReturn, Voucher voucher) {
        Set<VoucherItem> voucherItems = new HashSet();
        saleReturn.getSaleItems().forEach(
                saleReturnItem -> {
                    VoucherItem voucherItem = new VoucherItem();
                    voucherItem.setVoucher(voucher);    // 凭证主表
                    voucherItem.setOwner(saleReturnItem.getOwner());

                    voucherItem.setProduct(saleReturnItem.getProduct());
                    voucherItem.setUom(saleReturnItem.getUom());
                    voucherItem.setProductQty(-1.00 * saleReturnItem.getProductUomQty());

                    voucherItem.setOriginItemId(saleReturnItem.getId());
                    voucherItem.setSourceItemId(String.valueOf(saleReturnItem.getId()));
                    voucherItem.setSupplier(saleReturnItem.getSupplier());

                    VoucherItem source = voucherItem.findVoucherItem(saleReturnItem.getRetailOrderItem().getId());
                    if (source == null)
                        throw new RuntimeException("没有找到原单明细：" + saleReturnItem.getRetailOrderItem().getId() + " 的业务凭证！");
                    voucherItem.setVoucherItem(source);

                    // 重新赋值税率、商品价格、折扣
                    voucherItem.setTax(source.getTax());
                    voucherItem.setPriceUnit(source.getPriceUnit());
                    voucherItem.setDiscount(-1.00 * Math.abs(source.getDiscount()));
                    voucherItems.add(voucherItem);
                });
        return voucherItems;
    }
}
